//
// Created by Win on 2015/12/15.
//
#include <stdio.h>
#include <stdlib.h>

#include "frbyte_buffer.h"
#include "dcom_comm.h"
#include "dcom_remote_create.h"

int dcom_rpc_this(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0;
    int i_flag = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    //version
    i_ret = bytebuff_skip (p_st_data, 4);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //    Flags: INFO_LOCAL (0x00000001)
    i_ret = bytebuff_get_int (p_st_data, 4, (uint32_t *)&i_flag, (LITTLE_BIG_ENDIAN)p_st_private->i_packet_endian);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_skip (p_st_data, 4);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //
    switch (i_flag)
    {
        //INFO_NULL
        case 0:
            //todo
            break;

        //INFO_LOCAL
        case 1:
            //Causality ID: 936d5c19-2f78-4318-88b2-270dfb872beb
            i_ret = bytebuff_skip (p_st_data, 16);
            if(i_ret == FR_FAIL)
                return FR_FAIL;

        default:
            return FR_FAIL;
    }

    return FR_SUCC;

}


int remote_custom_comm_header(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    char c_tmp;
    int i_ret = 0, i_tmp = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    //VERSION
    i_ret = bytebuff_skip (p_st_data, 1);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //endianness
    i_ret = bytebuff_get_char (p_st_data, (uint8_t *)&c_tmp);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if(c_tmp & 0x10)
        p_st_private->i_packet_endian = BYTE_LITTLE_ENDIAN;
    else
        p_st_private->i_packet_endian = BYTE_BIG_ENDIAN;

    //common header len
    i_ret = bytebuff_get_int (p_st_data, 2, (uint32_t *)&i_tmp, (LITTLE_BIG_ENDIAN)p_st_private->i_packet_endian);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_skip (p_st_data, i_tmp - 4);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}

int remote_custom_private_header(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0, i_tmp = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    //object buff len
    i_ret = bytebuff_get_int (p_st_data, 4, (uint32_t *)&i_tmp, (LITTLE_BIG_ENDIAN)p_st_private->i_packet_endian);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //filter
    i_ret = bytebuff_skip (p_st_data, 4);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_skip (p_st_data, i_tmp);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}

int remote_custom_header(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    //common header
    i_ret = remote_custom_comm_header(p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //private header
    i_ret = remote_custom_private_header(p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}


int remote_special_system_properties(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    //commheader
    i_ret = remote_custom_comm_header (p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //private header
    i_ret = remote_custom_private_header(p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}

int remote_instantiation_info(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0;
    int i_all_len = 0, i_interface_id_count = 0;
    char *p_object_uuid = NULL, *p_interface_id = NULL;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    //commheader
    i_ret = remote_custom_comm_header (p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //private header
    //len
    i_ret = bytebuff_get_int (p_st_data, 4, (uint32_t *)&i_all_len, (LITTLE_BIG_ENDIAN)p_st_private->i_packet_endian);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //Filler: 0x00000000
    i_ret = bytebuff_skip (p_st_data, 4);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //InstantiatedObjectClsId: 330e9e79-df48-11cf-8e2c-00a0c90dc94b
    i_ret = dcom_ctx_guid(p_st_data, p_st_private, &p_object_uuid, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;
    i_all_len -= 16;

    //TODO
    if(p_object_uuid)
    {
        frfree(p_object_uuid);
    }

    //ClassContext    ActivationFlags    FlagsSurrogate: 0
    i_ret = bytebuff_skip (p_st_data, 12);
    if(i_ret == FR_FAIL)
        return FR_FAIL;
    i_all_len -= 12;

    //InterfaceIdCount: 1
    i_ret = bytebuff_get_int (p_st_data, 4, (uint32_t *)&i_interface_id_count, (LITTLE_BIG_ENDIAN)p_st_private->i_packet_endian);
    if(i_ret == FR_FAIL)
        return FR_FAIL;
    i_all_len -= 4;

    while (i_interface_id_count)
    {
        //InterfaceIds: IDrawServ (330e9e75-df48-11cf-8e2c-00a0c90dc94b)
        i_ret = dcom_ctx_guid (p_st_data, p_st_private, &p_interface_id, i_flag_need);
        if(i_ret == FR_FAIL)
            return FR_FAIL;
        i_all_len -= 16;
        //TODO
        if(p_interface_id)
        {
            frfree(p_interface_id);
            p_interface_id = NULL;
        }

        i_interface_id_count --;

    }

    i_ret = bytebuff_skip (p_st_data, i_all_len);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}

int remote_activation_context_info(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    //commheader
    i_ret = remote_custom_comm_header (p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //private header
    i_ret = remote_custom_private_header(p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}

int remote_security_info(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    //commheader
    i_ret = remote_custom_comm_header (p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //private header
    i_ret = remote_custom_private_header(p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}

int remote_local_info(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    //commheader
    i_ret = remote_custom_comm_header (p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //private header
    i_ret = remote_custom_private_header(p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}

int remote_scmrequest_info(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    //commheader
    i_ret = remote_custom_comm_header (p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //private header
    i_ret = remote_custom_private_header(p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}

int remote_iact_properties_req(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    //SpecialSystemProperties
    i_ret = remote_special_system_properties (p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //InstantiationInfo
    i_ret = remote_instantiation_info (p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //ActivationContextInfo
    i_ret = remote_activation_context_info (p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //SecurityInfo
    i_ret = remote_security_info (p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //LocationInfo
    i_ret = remote_local_info (p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //ScmRequestInfo
    i_ret = remote_scmrequest_info (p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}


int iact_properties_output(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0;
    int i_all_len = 0;
    int i_interface_count = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    //commheader
    i_ret = remote_custom_comm_header (p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //private header
    i_ret = bytebuff_get_int (p_st_data, 4, (uint32_t *)&i_all_len, (LITTLE_BIG_ENDIAN)p_st_private->i_packet_endian);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_skip (p_st_data, 4);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //NumInterfaces: 1
    i_ret = bytebuff_get_int (p_st_data, 4, (uint32_t *)&i_interface_count, (LITTLE_BIG_ENDIAN)p_st_private->i_packet_endian);
    if(i_ret == FR_FAIL)
        return FR_FAIL;
    i_all_len -= 4;

    while (i_interface_count)
    {
        //InterfaceIdsPtr
//        i_ret = interface_ids_ptr(p_st_data, p_st_private, p_st_body_data, i_flag_need);
//        if(i_ret == FR_FAIL)
//            return FR_FAIL;
        i_ret = bytebuff_skip (p_st_data, 8);
        if(i_ret == FR_FAIL)
            return FR_FAIL;




    }

    return FR_SUCC;

}



int iact_reply_info(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    //commheader
    i_ret = remote_custom_comm_header (p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //private header
    i_ret = remote_custom_private_header(p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}


int remote_iact_properties_resp(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    //PropertiesOutput
    i_ret = iact_properties_output(p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //ScmReplyInfo
    //todo
    i_ret = iact_reply_info(p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}

int remote_custom_iact_properties(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    //Totalsize: 688
    //Reserved: 0
    i_ret = bytebuff_skip (p_st_data, 8);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //CustomHeader
    i_ret = remote_custom_header(p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //Properties
    if(p_st_private->i_use_request)
        i_ret = remote_iact_properties_req(p_st_data, p_st_private, p_st_body_data, i_flag_need);
    else
        i_ret = remote_iact_properties_resp(p_st_data, p_st_private, p_st_body_data, i_flag_need);

    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}

int remote_custom_object_ref(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    //CLSID: 00000338-0000-0000-c000-000000000046
    //CBExtension: 0
    //Size: 704
    i_ret = bytebuff_skip (p_st_data, 24);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //IActProperties
    i_ret = remote_custom_iact_properties(p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}


int remote_iact_properties(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0;
    int i_flag = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    //2个 长度
    i_ret = bytebuff_skip (p_st_data, 8);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //object ref
    //Signature: MEOW
    i_ret = bytebuff_skip (p_st_data, 4);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //flags
    i_ret = bytebuff_get_int (p_st_data, 4, (uint32_t *)&i_flag, (LITTLE_BIG_ENDIAN)p_st_private->i_packet_endian);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //IID: 000001a2-0000-0000-c000-000000000046
    i_ret = bytebuff_skip (p_st_data, 16);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    switch (i_flag)
    {
        case 0x04:
            //CUSTOMOBJREF
            i_ret = remote_custom_object_ref(p_st_data, p_st_private, p_st_body_data, i_flag_need);
            if(i_ret == FR_FAIL)
                return FR_FAIL;

            break;

        default:
            return FR_FAIL;

    }

    return FR_SUCC;

}



int interface_ptrs_ptr(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0;
    int i_max_count = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    //Referent ID: 0x00020008
    i_ret = bytebuff_skip (p_st_data, 4);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //IID: IDrawServ (330e9e75-df48-11cf-8e2c-00a0c90dc94b)
    i_max_count *= 16;
    i_ret = bytebuff_skip (p_st_data, i_max_count);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}


/*!
 * ISystemActivator ISystemActivator Resolver, RemoteCreateInstance 解析
 *
 * \p_st_data               (入力参数)
 * \p_st_private            (私有数据)
 * \p_st_body_data          (上报链表)
 * \i_flag_need             (是否获取上报信息)
 *
 * \return FR_FAIL:失败\n
 *         FR_SUCC:成功\n
 *
 */
int dcom_remote_create_req(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    //dcom info
    i_ret = dcom_rpc_this(p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //No Specification Available: 00000000
//    i_ret = bytebuff_skip (p_st_data, 4);
    i_ret = bytebuff_skip (p_st_data, 4);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = remote_iact_properties(p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}

int dcom_rpc_that(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    // Flags: INFO_LOCAL (0x00000001)
    i_ret = bytebuff_skip (p_st_data, 12);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}


int dcom_remote_create_resp(Frbyte_Packet *p_st_data, L7session_dcom_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0;
    int i_response_code = 0;

    if(p_st_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    //DCOM, ORPCThat
    i_ret = dcom_rpc_that(p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //IActProperties
    i_ret = remote_iact_properties(p_st_data, p_st_private, p_st_body_data, i_flag_need);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_ret = bytebuff_get_int (p_st_data, 4, (uint32_t *)&i_response_code, (LITTLE_BIG_ENDIAN)p_st_private->i_packet_endian);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;

}


